export default class TaskFly {
  constructor(viewer, arr, view = 1) {
    this.viewer = viewer

    //时间间隔（S）  指两个点所需要的时间
    this.interval = 2

    this.index = 0 //差值经纬度索引
    this.maxIndex = 0 //最大差值经纬度数组索引
    this.pathIndex = 0 //当前经纬度数组索引
    this.forNum = 5 //差值间隔
    this.isLookAt = true //锁定视角
    this.autoDirection = true //自动调整方向
    this.lineNumner = [] //存路线数组
    this.Primitive = null
    this.entityPath = null
    this.entityPath1 = null //贴地线
    this.hpRoll = new Cesium.HeadingPitchRoll()
    this.linePath = [] //Cesium.Cartesian3
    this.showPath = [] //Cesium.Cartesian3

    this.timer = null

    //第一人称  第三人称
    this.view = view

    this.fixedFrameTransform = Cesium.Transforms.eastNorthUpToFixedFrame
    this.start(arr)
  }

  //轨迹开始
  /*
   * arr是轨迹点集合
   */

  start = (arr) => {
    if (arr.length === 0) return
    this.showPath = []
    //插入坐标
    arr.forEach((item, index) => {
      if (index > 0) {
        this.showPath = this.showPath.concat(
          this.getPosition(
            Cesium.Cartesian3.fromDegrees(
              arr[index - 1][0],
              arr[index - 1][1],
              arr[index - 1][2]
            ),
            Cesium.Cartesian3.fromDegrees(item[0], item[1], item[2]),
            this.interval,
            2
          )
        )
      }
    })
    console.log(this.showPath)
    //初始化视角
    // this.viewer.camera.flyTo({
    //   destination: Cesium.Cartesian3.fromDegrees(
    //     113.14866683236643,
    //     27.86994208684573,
    //     arr[0][2] + 700
    //   ), //设置位置
    //   orientation: {
    //     heading: Cesium.Math.toRadians(223),
    //     pitch: Cesium.Math.toRadians(-50),
    //     roll: 0,
    //   },
    // })

    this.index = 1
    this.maxIndex = this.showPath.length - 1
    this.initModel()
    this.timer = setInterval(() => {
      this.render()
    }, 20)
    // this.viewer.scene.preUpdate.addEventListener(this.render)
  }

  update = (arr) => {
    //更新坐标插入
    arr.forEach((item, index) => {
      if (index > 0) {
        this.showPath = this.showPath.concat(
          this.getPosition(
            Cesium.Cartesian3.fromDegrees(
              arr[index - 1][0],
              arr[index - 1][1],
              arr[index - 1][2]
            ),
            Cesium.Cartesian3.fromDegrees(item[0], item[1], item[2]),
            this.interval,
            2
          )
        )
        this.maxIndex = this.showPath.length - 1
      }
    })
  }

  //稀释轨迹点
  getPosition = (startP, endP, duration, speed = 1) => {
    let arr = []
    // 这里是ms  1000是1S  speed来控制速度大小
    duration = (duration * 1000) / speed
    for (let i = 0; i <= duration; i = i + this.forNum) {
      let pos = Cesium.Cartesian3.lerp(
        startP,
        endP,
        i / duration,
        new Cesium.Cartesian3()
      )
      arr.push(pos)
    }
    if (duration % this.forNum !== 0) {
      arr.push(endP)
    }
    return arr
  }

  //修改视角
  changeView = () => {
    if (this.view === 1) {
      // this.Primitive.show = false
      // this.entityPath.show = false
      this.view = 3
    } else {
      // this.Primitive.show = true
      // this.entityPath.show = true
      this.view = 1
    }
  }

  //暂停开始
  playPause = () => {
    if (this.timer) {
      clearInterval(this.timer)
      this.timer = null
      this.autoDirection = false //暂停时不自动调整方向
    } else {
      this.timer = setInterval(() => {
        this.render()
      }, 20)
      this.autoDirection = true //恢复时自动调整方向
    }
  }

  lerpAngle = (a, b, t) => {
    let delta = b - a
    delta = ((delta + Math.PI) % (2 * Math.PI)) - Math.PI

    return a + delta * t
  }

  render = () => {
    //大于的时候 行程走完了
    if (this.index > this.maxIndex) {
      this.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
      return
    }
    if (this.autoDirection) {
      // const heading = this.getHeading(
      //   this.showPath[this.index - 1],
      //   this.showPath[this.index]
      // )
      // if (heading) this.hpRoll.heading = heading

      const current = this.showPath[this.index - 1]
      const next = this.showPath[this.index]
      const headingNow = this.getHeading(current, next)

      const distance = Cesium.Cartesian3.distance(current, next)
      console.log(distance)

      if (headingNow !== undefined) {
        const lastHeading = this.hpRoll.heading || 0
        const lerpedHeading = this.lerpAngle(lastHeading, headingNow, 0.05) // 0.1 为平滑系数，越小越慢
        this.hpRoll.heading = lerpedHeading
      }

      this.linePath.push(this.showPath[this.index])
      Cesium.Transforms.headingPitchRollToFixedFrame(
        this.showPath[this.index],
        {
          heading: Cesium.Math.toRadians(90),
          pitch: 0,
          roll: 0,
        },
        // this.hpRoll,
        Cesium.Ellipsoid.WGS84,
        this.fixedFrameTransform,
        this.Primitive.modelMatrix
      )
      if (this.isLookAt) {
        this.viewer.camera.lookAt(
          this.showPath[this.index],
          // heading：朝向角度
          // pitch：俯仰角（0 表示水平看向目标，负值往下看）
          // range：距离目标多远
          new Cesium.HeadingPitchRange(
            this.hpRoll.heading,
            Cesium.Math.toRadians(this.view === 1 ? -15 : -89),
            this.view === 1 ? 100 : 200
          )
        )
      }
      this.index += 1
    }
  }

  // 绘制特效线
  addline() {
    var polylineinstance1 = new Cesium.GeometryInstance({
      //PolylineGeometry 不贴地  GroundPolylineGeometry 贴地
      geometry: new Cesium.PolylineGeometry({
        positions: this.showPath,
        width: 6,
      }),
      vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
    })

    //Primitive 不贴地  GroundPolylinePrimitive 贴地
    this.entityPath1 = this.viewer.scene.primitives.add(
      new Cesium.Primitive({
        show: true,
        geometryInstances: [polylineinstance1],
        appearance: new Cesium.PolylineMaterialAppearance({
          material: Cesium.Material.fromType('DynamicGlow', {
            color: Cesium.Color.fromCssColorString('#3a3916'),
          }),
        }),
      })
    )

    var polylineinstance = new Cesium.GeometryInstance({
      geometry: new Cesium.PolylineGeometry({
        positions: this.showPath,
        width: 10,
      }),
      vertexFormat: Cesium.PolylineMaterialAppearance.VERTEX_FORMAT,
    })
    this.entityPath = this.viewer.scene.primitives.add(
      new Cesium.Primitive({
        geometryInstances: [polylineinstance],
        appearance: new Cesium.PolylineMaterialAppearance({
          material: Cesium.Material.fromType('DynamicGlow', {
            color: Cesium.Color.fromCssColorString('#8f8b19'),
            repeat: new Cesium.Cartesian2(1, 1),
            speed: 7,
            image: 'imgs/lineAarrow.png',
            axisY: false,
          }),
        }),
      })
    )
  }

  //加载模型
  initModel = () => {
    let pos = this.showPath[0]

    this.linePath = [pos]
    this.Primitive = this.viewer.scene.primitives.add(
      //加载模型
      Cesium.Model.fromGltf({
        url: 'data/model/wurenji.glb',
        modelMatrix: Cesium.Transforms.headingPitchRollToFixedFrame(
          pos,
          // {
          //   heading: Cesium.Math.toRadians(90),
          //   pitch: 0,
          //   roll: 0,
          // },
          this.hpRoll,

          Cesium.Ellipsoid.WGS84,
          this.fixedFrameTransform
        ),
        scale: 10,
      })
    )

    this.Primitive.readyPromise.then((model) => {
      model.activeAnimations.addAll({
        loop: Cesium.ModelAnimationLoop.REPEAT,
        // speedup: 1.0,
      })
    })

    this.addline()

    this.entityPath = this.viewer.entities.add({
      position: pos,
      //轨迹线
      polyline: {
        // positions: new Cesium.CallbackProperty(() => {
        //   return this.linePath
        // }, false),
        positions: this.showPath,
        show: true,
        arcType: Cesium.ArcType.RHUMB,
        material: Cesium.Color.YELLOW.withAlpha(0.5), //线条颜色
        width: 1.5,
        // clampToGround: true, //是否贴地,
        // classificationType: Cesium.ClassificationType.BOTH //也贴模型
      },
    })
  }

  // 根据两个坐标点,获取Heading(朝向)
  getHeading = (pointA, pointB) => {
    if (pointA.x === pointB.x && pointA.y === pointB.y) return
    //建立以点A为原点，X轴为east,Y轴为north,Z轴朝上的坐标系
    const transform = Cesium.Transforms.eastNorthUpToFixedFrame(pointA)
    //向量AB
    const positionvector = Cesium.Cartesian3.subtract(
      pointB,
      pointA,
      new Cesium.Cartesian3()
    )
    //因transform是将A为原点的eastNorthUp坐标系中的点转换到世界坐标系的矩阵
    //AB为世界坐标中的向量
    //因此将AB向量转换为A原点坐标系中的向量，需乘以transform的逆矩阵。
    const vector = Cesium.Matrix4.multiplyByPointAsVector(
      Cesium.Matrix4.inverse(transform, new Cesium.Matrix4()),
      positionvector,
      new Cesium.Cartesian3()
    )
    //归一化
    const direction = Cesium.Cartesian3.normalize(
      vector,
      new Cesium.Cartesian3()
    )
    //heading
    const heading =
      Math.atan2(direction.y, direction.x) - Cesium.Math.PI_OVER_TWO
    return Cesium.Math.TWO_PI - Cesium.Math.zeroToTwoPi(heading)
  }

  clear = () => {
    if (this.timer) {
      clearInterval(this.timer)
    }
    if (this.Primitive) {
      this.viewer.scene.primitives.remove(this.Primitive)
    }

    if (this.entityPath) {
      this.viewer.entities.remove(this.entityPath)
    }
    if (this.entityPath1) {
      this.viewer.scene.primitives.remove(this.entityPath1)
    }

    this.viewer.scene.preUpdate.removeEventListener(this.render)
    this.viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)

    //时间间隔（S）
    this.interval = 2
    this.index = 0 //差值经纬度索引
    this.maxIndex = 0 //最大差值经纬度数组索引
    this.pathIndex = 0 //当前经纬度数组索引
    this.forNum = 5 //差值间隔
    this.isLookAt = false //锁定视角
    this.autoDirection = true //自动调整方向
    this.lineNumner = [] //存路线数组
    this.Primitive = null
    this.entityPath = null
    this.entityPath1 = null //贴地线
    this.hpRoll = new Cesium.HeadingPitchRoll()
    this.linePath = [] //Cesium.Cartesian3
    this.showPath = [] //Cesium.Cartesian
  }
}
